package org.wattdepot.gdata.kukuicup.updater;

import it.sauronsoftware.cron4j.Task;
import it.sauronsoftware.cron4j.TaskExecutionContext;
import java.net.URL;
import java.util.Date;
import org.wattdepot.gdata.kukuicup.service.GDataService;
import org.wattdepot.gdata.kukuicup.service.WattDepotService;

/**
 * A superclass for all GData Cron4J Task implementations.
 * Provides common fields and operations for all GData tasks and specifies required methods. 
 * Unfortunately, this superclass is just like GDataTask!
 *  
 * @author Philip Johnson
 */
public abstract class GDataCronTask extends Task {
  
  /** Supports connecting to a WattDepot server and getting KukuiCup data. */
  protected WattDepotService wattDepotService;
  /** Supports connecting to a Google Docs spreadsheet and writing data to it. */
  protected GDataService gdataService;
  /** The source to be analyzed. */
  protected String sourceName;
  /** The row to be updated by this task. */
  protected int row;
  /** The URL of the spreadsheet that will be updated by this task. */
  protected URL spreadsheetURL;
  /** Stores the start time of WattDepot processing. */
  private long wattDepotStartTime = 0;
  /** Stores the elapsed time of WattDepot processing. */
  private long wattDepotElapsedTime = 0;
  /** Stores the start time of GData processing. */
  private long gdataStartTime = 0;
  /** Stores the elapsed time of GData processing. */
  private long gdataElapsedTime = 0;
  /** The name of this task (set by subclasses). */
  protected String name;
  /** Whether or not the source operating on by this task is virtual. */
  protected boolean isVirtual;

  /**
   * Initializes a GDataTask with required configuration data. 
   * @param wattDepotService The WattDepotService.
   * @param gdataService The GDataService.
   * @param spreadsheetURL The URL for this spreadsheet.
   * @param sourceName The WattDepot source that this task will analyze.
   * @param row The row this source's data appears in.
   * @param name The name of this task. 
   * @param isVirtual If this source is a virtual source.
   */
  public GDataCronTask(WattDepotService wattDepotService, GDataService gdataService, 
      URL spreadsheetURL, String sourceName, int row, String name, boolean isVirtual) {
    this.wattDepotService = wattDepotService;
    this.gdataService = gdataService;
    this.sourceName = sourceName;
    this.row = row;
    this.spreadsheetURL = spreadsheetURL;
    this.name = name;
    this.isVirtual = isVirtual;
  }

  @Override
  public abstract void execute(TaskExecutionContext arg0) throws RuntimeException;
  
  /**
   * Allows the subtask to indicate that wattdepot timing has started.
   */
  protected void startWattDepotTiming() {
    this.wattDepotStartTime = (new Date()).getTime();
  }
  
  /**
   * Allows the subtask to indicate that wattdepot timing has ended.
   */
  protected void stopWattDepotTiming() {
    this.wattDepotElapsedTime = (new Date()).getTime() - this.wattDepotStartTime;
  }
  
  /**
   * Allows the subtask to indicate that GData timing has started.
   */
  protected void startGDataTiming() {
    this.gdataStartTime = (new Date()).getTime();
  }
  
  /**
   * Allows the subtask to indicate that GData timing has ended.
   */
  protected void stopGDataTiming() {
    this.gdataElapsedTime = (new Date()).getTime() - this.gdataStartTime;
  }
  
  /**
   * The standard string to be printed out when a task finishes processing.
   * In addition to the parameters, it will print the name, the source, and the elapsed times.
   * @param value The value computed by the task.
   * @param units The units (watts or watt-hrs).
   * @param lastUpdate The time that this task finished executing.
   */
  protected void printTaskResults(String value, String units, String lastUpdate) {
    System.out.format("%s %20s: %10s %7s %8s %s (WattDepot: %s, GData: %s)%n", getTimestamp(),
        name, sourceName, value, units, lastUpdate, wattDepotElapsedTime, gdataElapsedTime);
  }
  
  /**
   * Returns the current time as MM/dd/yy HH:mm:ss.
   * @return The current timestamp.
   */
  protected String getTimestamp() {
    return new java.text.SimpleDateFormat("MM/dd/yy HH:mm:ss").format(new Date());
  }

}
